package com.wzw.expression.expression.object;

import com.wzw.expression.expression.exception.VariableNotAvailableException;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Wangzhiwen
 */
public class GeneralEvaluationContext extends MethodBasedEvaluationContext {

    /**
     * 无结果返回
     */
    protected static final Object NO_RESULT = new Object();

    /**
     * 返回结果不可用
     */
    protected static final Object RESULT_UNAVAILABLE = new Object();

    /**
     * 错误信息key
     */
    public static final String ERROR_VARIABLE = "error";

    /**
     * 返回结果key
     */
    public static final String RESULT_VARIABLE = "result";

    private final Set<String> unavailableVariables = new HashSet<>(1);

    public GeneralEvaluationContext(Object rootObject, Method method, Object[] arguments, ParameterNameDiscoverer parameterNameDiscoverer) {
        super(rootObject, method, arguments, parameterNameDiscoverer);
    }

    public void addErrorVariable(String error) {
        this.setVariable(ERROR_VARIABLE, error);
    }

    public void addResultVariable(Object result) {
        if (result == RESULT_UNAVAILABLE) {
            this.addUnavailableVariable(RESULT_VARIABLE);
        }
        if (result != NO_RESULT) {
            this.setVariable(RESULT_VARIABLE, result);
        }
    }

    public void addUnavailableVariable(String name) {
        this.unavailableVariables.add(name);
    }

    @Override
    @Nullable
    public Object lookupVariable(@NonNull String name) {
        if (this.unavailableVariables.contains(name)) {
            throw new VariableNotAvailableException(name);
        }
        return super.lookupVariable(name);
    }
}
